import 'dart:io';
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:path/path.dart' as path;
import 'package:mime/mime.dart';
import 'package:uuid/uuid.dart';
import '../../../models/chunk_upload.dart';
import '../chunk_upload_service.dart';
import '../../file_service.dart';
import 'package:flutter/material.dart';
import '../../../screens/upload_tasks_screen.dart';
import '../../../config/upload_config.dart';

class UploadManager {
  // 单例实例
  static final UploadManager _instance = UploadManager._internal();

  // 工厂构造函数
  factory UploadManager() => _instance;

  // 内部构造函数
  UploadManager._internal();

  // 获取上传任务流
  Stream<List<UploadTask>> get uploadTasksStream =>
      ChunkUploadService.uploadTasksStream;

  // 获取上传任务列表
  List<UploadTask> get uploadTasks => ChunkUploadService.uploadTasks;

  // 获取待上传任务
  List<UploadTask> get pendingTasks =>
      uploadTasks
          .where((task) => task.status == UploadTaskStatus.pending)
          .toList();

  // 获取上传中任务
  List<UploadTask> get uploadingTasks =>
      uploadTasks
          .where((task) => task.status == UploadTaskStatus.uploading)
          .toList();

  // 获取已完成任务
  List<UploadTask> get completedTasks =>
      uploadTasks
          .where((task) => task.status == UploadTaskStatus.completed)
          .toList();

  // 获取失败任务
  List<UploadTask> get failedTasks =>
      uploadTasks
          .where(
            (task) =>
                task.status == UploadTaskStatus.failed ||
                task.status == UploadTaskStatus.canceled,
          )
          .toList();

  // 添加文件上传任务
  Future<UploadTask> addFileUpload(
    String filePath, {
    int directoryId = 0,
  }) async {
    final task = await _addFileUploadWithoutStarting(
      filePath,
      directoryId: directoryId,
    );

    // 立即开始上传
    await ChunkUploadService.startUploadTask(task.id);

    return task;
  }

  // 添加多个文件上传任务
  Future<List<UploadTask>> addFilesUpload(
    List<String> filePaths, {
    int directoryId = 0,
    BuildContext? context,
  }) async {
    final tasks = <UploadTask>[];
    final largeFiles = <String>[];

    // 第一步：检查大文件
    if (!kIsWeb) {
      for (final filePath in filePaths) {
        final file = File(filePath);
        if (await file.length() > UploadConfig.largeFileThreshold) {
          largeFiles.add(path.basename(filePath));
        }
      }
    }

    // 如果有大文件，通知订阅者
    if (largeFiles.isNotEmpty) {
      for (final fileName in largeFiles) {
        _largeFileNotificationController.add(fileName);
      }
    }

    // 第二步：添加所有任务但不立即上传
    for (final filePath in filePaths) {
      try {
        final task = await _addFileUploadWithoutStarting(
          filePath,
          directoryId: directoryId,
        );
        tasks.add(task);
      } catch (e) {
        print('添加文件上传任务失败: $e');
      }
    }

    // 第三步：一次性开始所有上传任务
    for (final task in tasks) {
      try {
        await ChunkUploadService.startUploadTask(task.id);
      } catch (e) {
        print('开始上传任务失败: ${task.fileName}, 错误: $e');
      }
    }

    return tasks;
  }

  // 添加文件上传任务但不立即开始上传
  Future<UploadTask> _addFileUploadWithoutStarting(
    String filePath, {
    int directoryId = 0,
  }) async {
    if (kIsWeb) {
      throw Exception('Web平台不支持通过文件路径上传');
    }

    try {
      final file = File(filePath);
      if (!await file.exists()) {
        throw Exception('文件不存在：$filePath');
      }

      // 获取文件名
      final fileName = path.basename(filePath);

      // 获取文件大小
      final fileSize = await file.length();

      // 获取文件MIME类型
      final mimeType = lookupMimeType(filePath) ?? 'application/octet-stream';

      // 添加上传任务
      final (task, isLargeFile) = await ChunkUploadService.addUploadTask(
        filePath: filePath,
        fileName: fileName,
        fileSize: fileSize,
        mimeType: mimeType,
        directoryId: directoryId,
      );

      return task;
    } catch (e) {
      print('添加文件上传任务失败: $e');
      rethrow;
    }
  }

  // 添加字节数据上传任务
  Future<UploadTask> addBytesUpload(
    Uint8List bytes,
    String fileName, {
    String? mimeType,
    String? filePath,
    int directoryId = 0,
  }) async {
    print('准备添加字节数据上传任务: $fileName');
    final fileSize = bytes.length;
    final detectedMimeType = mimeType ?? _guessMimeType(fileName, bytes);

    print('字节数据信息: 大小=$fileSize, 类型=$detectedMimeType');

    try {
      // 添加上传任务
      final (task, isLargeFile) = await ChunkUploadService.addUploadTask(
        filePath: filePath ?? fileName,
        fileName: fileName,
        fileSize: fileSize,
        mimeType: detectedMimeType,
        directoryId: directoryId,
      );

      // 立即开始上传
      print('立即开始上传任务: ${task.id}');
      await ChunkUploadService.startUploadTask(task.id);

      return task;
    } catch (e) {
      print('添加上传任务失败: $e');
      rethrow;
    }
  }

  // 开始所有待上传任务
  Future<void> startAllPendingTasks() async {
    final tasks = pendingTasks;

    for (final task in tasks) {
      await ChunkUploadService.startUploadTask(task.id);
    }
  }

  // 开始指定上传任务
  Future<void> startUploadTask(String taskId) async {
    await ChunkUploadService.startUploadTask(taskId);
  }

  // 暂停上传任务
  void pauseUploadTask(String taskId) {
    ChunkUploadService.pauseUploadTask(taskId);
  }

  // 恢复上传任务
  void resumeUploadTask(String taskId) {
    ChunkUploadService.resumeUploadTask(taskId);
  }

  // 取消上传任务
  void cancelUploadTask(String taskId) {
    ChunkUploadService.cancelUploadTask(taskId);
  }

  // 移除上传任务
  void removeUploadTask(String taskId) {
    ChunkUploadService.removeUploadTask(taskId);
  }

  // 清除已完成的任务
  void clearCompletedTasks() {
    ChunkUploadService.clearCompletedTasks();
  }

  // 根据文件名和字节数据猜测MIME类型
  String _guessMimeType(String fileName, Uint8List bytes) {
    // 先尝试通过文件扩展名猜测
    final mimeType = lookupMimeType(fileName);
    if (mimeType != null) {
      return mimeType;
    }

    // 如果无法通过扩展名猜测，尝试通过文件头猜测
    if (bytes.length > 4) {
      // JPEG: FF D8 FF
      if (bytes[0] == 0xFF && bytes[1] == 0xD8 && bytes[2] == 0xFF) {
        return 'image/jpeg';
      }

      // PNG: 89 50 4E 47
      if (bytes[0] == 0x89 &&
          bytes[1] == 0x50 &&
          bytes[2] == 0x4E &&
          bytes[3] == 0x47) {
        return 'image/png';
      }

      // GIF: 47 49 46 38
      if (bytes[0] == 0x47 &&
          bytes[1] == 0x49 &&
          bytes[2] == 0x46 &&
          bytes[3] == 0x38) {
        return 'image/gif';
      }

      // PDF: 25 50 44 46
      if (bytes[0] == 0x25 &&
          bytes[1] == 0x50 &&
          bytes[2] == 0x44 &&
          bytes[3] == 0x46) {
        return 'application/pdf';
      }

      // ZIP: 50 4B 03 04
      if (bytes[0] == 0x50 &&
          bytes[1] == 0x4B &&
          bytes[2] == 0x03 &&
          bytes[3] == 0x04) {
        return 'application/zip';
      }
    }

    // 默认返回二进制流
    return 'application/octet-stream';
  }

  // 大文件通知流控制器
  static final _largeFileNotificationController =
      StreamController<String>.broadcast();

  // 获取大文件通知流
  Stream<String> get largeFileNotificationStream =>
      _largeFileNotificationController.stream;

  // 销毁
  void dispose() {
    _largeFileNotificationController.close();
  }
}
